
// This guard ensures that windows implementation is used only
// on windows platform.
#ifndef MY_USE_WIN32

    #error Windows version of __FILE__ is used without MY_USE_WIN32 defined.

#endif

#include <algorithm>
#include <cstdlib>

#include "Core/Win32/WindowImp.hpp"
#include "Debug/Assert.hpp"

namespace My
{
    LPCTSTR WindowImp::s_WindowClassName = TEXT("MyWindowClassWin32");

    WindowImp::WindowImp(const std::string &title, uint32_t width, uint32_t height)
    {
        #ifdef UNICODE

            std::wstring encoded_title(title.size() + 1, L' ');
            std::copy(title.begin(), title.end(), encoded_title.begin());

        #else

            std::string encoded_title(title);

        #endif

        // Create window.
        m_Handle = CreateWindowEx(WS_EX_CLIENTEDGE,
                                  s_WindowClassName,
                                  encoded_title.c_str(),
                                  WS_OVERLAPPEDWINDOW,
                                  CW_USEDEFAULT, CW_USEDEFAULT, width, height,
                                  NULL, NULL, static_cast<HINSTANCE>(GetModuleHandle(NULL)), NULL);

        MY_ASSERT(m_Handle != NULL, "CreateWindowEx failed.");

        // Show & update.
        ShowWindow(m_Handle, SW_SHOWNORMAL);
        UpdateWindow(m_Handle);
    }

    WindowImp::~WindowImp() {}

    void WindowImp::Initialize()
    {
        WNDCLASSEX window_class_ex;
        window_class_ex.cbSize        = sizeof(WNDCLASSEX);
        window_class_ex.style         = 0;
        window_class_ex.lpfnWndProc   = WndProc;
        window_class_ex.cbClsExtra    = 0;
        window_class_ex.cbWndExtra    = 0;
        window_class_ex.hInstance     = static_cast<HINSTANCE>(GetModuleHandle(NULL));
        window_class_ex.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
        window_class_ex.hCursor       = LoadCursor(NULL, IDC_ARROW);
        window_class_ex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
        window_class_ex.lpszMenuName  = NULL;
        window_class_ex.lpszClassName = s_WindowClassName;
        window_class_ex.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

        ATOM atom = RegisterClassEx(&window_class_ex);
        MY_ASSERT(atom, "RegisterClassEx failed.");
    }

    LRESULT CALLBACK WindowImp::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
            case WM_DESTROY:

                PostQuitMessage(0);
                break;

            default:

                return DefWindowProc(hWnd, message, wParam, lParam);
                break;
        }

        return 0;
    }
}
